﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DVK.SP2007.UniversalClient;
using Microsoft.SharePoint;
using DVK.SP2007.Constants;

namespace DVK.SP2007
{
    /// <summary>
    /// Maps data from SendToDVK form into IDvkMessage.
    /// </summary>
    public class OutgoingMessageMapper : IMessageMapper<IDvkMessage>
    {
        public string DvkFolder { get; set; }
        public string Title { get; set; }
        public DateTime SendDate { get; set; }
        public UnitInfo Organisation { get; set; }
        public PersonMetadata Sender { get; set; }
        public List<SenderReceiverInfo> Recipients { get; set; }
        public PersonMetadata Author { get; set; }
        public List<PersonMetadata> Compilators { get; set; }
        public string DvkType { get; set; }
        public string DocumentVersion { get; set; }
        public string Comments { get; set; }
        public string DocumentLanguage { get; set; }
        public string DocumentType { get; set; }
        public bool UseAuthorOrganisation { get; set; }

        private SPListItem _newItem;
        private SPListItem _currentItem;
        private SPWeb _web;
        /// <summary>
        /// Initializes a new instance of the <see cref="IncomingMessageToDvkMessageMapper"/> class.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="currentItem">The current item.</param>
        /// <param name="newItem">The new item.</param>
        public OutgoingMessageMapper(SPWeb web, SPListItem currentItem, SPListItem newItem)
        {
            _currentItem = currentItem;
            _newItem = newItem;
            _web = web;
        }

        #region IMessageMapper<IDvkMessage> Members

        /// <summary>
        /// Maps metadata from somewhere into the object instance of type T.
        /// <remarks>
        /// Normally this means mapping information from different location into one format (object).
        /// e.g. to IDvkMessage or Inbox SPListItem.
        /// </remarks>
        /// </summary>
        /// <returns></returns>
        public IDvkMessage Map()
        {
            //Create DVK Message to map to listitem later and generate the DVK XML
            IDvkMessage message = new DvkMessage();
            message.FolderName = DvkFolder;
            message.IsIncoming = false;
            message.LocalItemId = _newItem.ID;
            message.SendingStatus = DvkSendingStatus.WaitingInDHS;
            message.Title = Title;
            message.SendingDate = SendDate;
            message.StatusUpdateNeeded = true;
            //Sender information
            message.Sender.Organisation = Organisation;
            message.Sender.Person = new UnitInfo() { Code = Sender.PersonCode, Name = Sender.PersonName };
            message.Sender.Email = Sender.Email;
            message.Sender.OrganisationUnit = new UnitInfo() { Name = Sender.DepartmentName };
            message.Sender.JobTitle = Sender.JobTitle;
            message.Sender.Telephone = Sender.Telephone;

            //Start creating DVK XML
            message.DataXml = new DvkXml();
            //Not nessecary

            //TransportXml - Sender
            message.DataXml.Transport.AddSender(
                    message.Sender
                );
            //TransportXml and MetaXml - Recipients
            foreach (var recipient in Recipients)
            {
                message.DataXml.Transport.AddRecipient(recipient);
                message.DataXml.MetaXml.AddAddressee(recipient);
            }

            //!!!! Important !!!!
            // TODO: Currently we are missing Signer/Approver and restriction rights
            // They can however be mapped through the mapping capability
            //!!!!!!!!!!!!!!!!!!!

            //MetaXml - Letter metadata
            DateTime? authorCompilerDate = DateTime.Now;

            message.DataXml.MetaXml.AddAuthor(message.Sender.Organisation.Name, Author, UseAuthorOrganisation);
            message.DataXml.MetaXml.AddCompilators(Compilators);
            message.DataXml.MetaXml.AddEnclosure(Comments);
            message.DataXml.MetaXml.AddOrUpdateLetterMetadata(authorCompilerDate, string.Empty, DvkType, DocumentLanguage, message.Title);
            message.DataXml.MetaXml.AddOrUpdateLetterMetadataElement<string>(DvkMetaXmlPart.ElementNameLetterMetadataVersion, DocumentVersion);

            //We add sender as signer
            message.DataXml.MetaXml.AddSignature(
                Sender.FirstName,
                Sender.SurName,
                Sender.JobTitle,
                Sender.Email,
                Sender.Telephone,
                null
                );

            //MetainfoXml information
            //Author adding
            if (Author != null)
            {
                message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameAuthorPersonCode, Author.PersonCode);
                message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameAuthorName, Author.PersonName);
            }

            //Additional standard metainfo
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameSenderDate, XmlHelper.GetISO8601DateTime(authorCompilerDate));
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameCompilerDocumentType, DocumentType);
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameCompilerDate, XmlHelper.GetISO8601DateTime(authorCompilerDate));
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameCompilerDocumentName, _currentItem.Name);
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameCompilerOrganizationCode, message.Sender.Organisation.Code);
            message.DataXml.Metainfo.AddMetainfo(DvkMetainfoXmlPart.ElementNameCompilerOrganizationName, message.Sender.Organisation.Name);

            //Map the metadata from SPListItem (source) to DVK xml.
            var metadataMappingList = new MetadataMappingRepository(_web).GetMapping(Fields.DvkMappingLevel.DvkMappingLevelChoices.Web, null, Fields.DvkMappingApplyingTo.DvkMappingApplyingToChoices.Out);
            foreach (var mapping in metadataMappingList)
            {
                message.DataXml.AddElement(
                        mapping.DvkParentElementName,
                        mapping.DvkElementName,
                        _currentItem[mapping.SPFieldName]
                    );
            }
            return message;
        }

        #endregion
    }
}
